/**
 * 横向柱状图
 * XYHorizontalChartsC (reactCharts)
 * @author zxy
 * @date  2020-09-17
 */
import React from 'react';
import PropTypes from 'prop-types';
import ReactEcharts from 'echarts-for-react';
import { Spin } from 'antd';
import { NoDataC } from '../../other';
import Color from '../../../css/colors';
import _ from 'lodash';

class XYHorizontalChartsC extends React.Component {
  // 入参默认值设置
  static defaultProps = {
    yAxis: undefined,
    series: undefined,
    type: 'normal', // 默认普通的横向柱状图
    height: '100%', // 图形高度默认为父节点的100%
    width: '100%', // 图形宽度默认为父节点的100%
    colors: Color.echart, // 默认系统色
    title: '', // 标题默认为空
    yAxisUnit: [], // 默认纵轴上无单位（从左向右，每一项用字符串数据表示）
    percentStyle: false, // 默认不按百分比样式展示
    separator: false, // 分隔符
    showBorder: false, // 默认不展示外边框
    toolTipFormat: undefined, // 默认按自定义的提示信息样式展示
    toolTipDataFormat: [], // 默认提示信息中的数据无任何
    seriesLabelDataFormat: [], // 默认不展示图形上的文本标签
    gridLeft: 20, // 默认左轴距离左侧距离为115
    gridRight: 60, // 默认右轴距离右侧距离为60
    isShowSeriesLabel: true, // 默认显示图形上的文本格式
    showLegend: true, // 默认展示图例
    yAxisPosition: 'left', // 纵轴位置默认在左侧
    onRef: () => {}, // 本组件的引用
    showTooltipLabel: true, // 默认展示提示信息在横轴和纵轴上的提示
    containLabel: true, // 默认grid区域是包含坐标轴的刻度标签
    click: () => {}, // 默认不响应click事件
  };

  debtAndProfitColor = Color.debtAndProfit.background; // type为收益负债模式时，固定显示的颜色

  componentDidMount() {
    // 父组件对本组件的引用
    this.props.onRef(this);
  }

  shouldComponentUpdate(nextProps) {
    let props = this.props ? JSON.stringify(this.props) : '';
    let propsN = nextProps ? JSON.stringify(nextProps) : '';
    if (props === propsN) {
      return false;
    } else {
      return true;
    }
  }

  click = (e) => {
    // 抛出点击事件
    this.props.click(e);
  };

  // 返回option
  getOption = (legend, series, paddingHeight) => {
    const {
      colors,
      title,
      showBorder,
      gridLeft,
      gridRight,
      yAxis,
      toolTipFormat,
      toolTipDataFormat,
      yAxisUnit,
      percentStyle,
      separator,
      showLegend,
      yAxisPosition,
      showTooltipLabel,
      containLabel,
    } = this.props;
    return {
      // 调色盘颜色列表
      color: colors,
      backgroundColor: Color.echartItems.bgColor, //echarts整个画布的背景色
      // 主标题和副标题
      title: {
        show: title ? true : false,
        left: '20',
        top: showBorder ? 30 : 20,
        text: title,
        textStyle: {
          color: Color.echartItems.title,
          fontSize: 14,
          fontWeight: 'normal',
          lineHeight: 20,
        },
      },
      // 鼠标移动上去提示信息
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'cross', // tooltip展示十字型
          crossStyle: {
            color: Color.echartItems.tooltipCross,
          },
          label: {
            backgroundColor: Color.echartItems.tooltipBg, //坐标轴指示器的背景颜色
            color: Color.echartItems.toolLable,
            padding: [7, 7, 5, 7],
            show: showTooltipLabel,
          },
        },
        formatter: toolTipFormat
          ? toolTipFormat
          : (params) => {
              let str = `<div style="color:${Color.echartItems.tooltipLabel}">`;
              str += `<div style="margin-bottom:12px">${params[0].name}</div>`;

              params.map((item) => {
                let value = item.value == null || item.value == undefined ? '--' : item.value;
                if (percentStyle) {
                  value = typeof value === 'number' && !isNaN(value) ? parseInt(Math.round(value * 10000)) / 100 + '%' : '--';
                }
                let yAxisIndex = -1;
                series.forEach((element) => {
                  if (element.name === item.seriesName) {
                    yAxisIndex = element.yAxisIndex;
                  }
                });
                if (toolTipDataFormat[yAxisIndex]) {
                  value = toolTipDataFormat[yAxisIndex](value);
                }
                str += `<div style="display:flex;align-items:center;margin-top:8px">
                           <div style="border:1px solid rgba(255,255,255,1);width:10px;height:10px;border-radius:50%;background-color:${item.color};margin-right:8px"></div> 
                           ${item.seriesName}： ${value}
                         </div>`;
              });
              str += '</div>';
              return str;
            },
        padding: [12, 12, 12, 12],
        confine: true, // 是否将 tooltip 框限制在图表的区域内
        backgroundColor: Color.echartItems.tooltipBgColor,
        extraCssText: `box-shadow: 0px 2px 12px 0px ${Color.echartItems.tooltipBgShadow};border-radius: 4px;opacity: 0.65;font-size: 12px;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;`,
      },
      // 图例
      legend: {
        data: legend,
        show: showLegend ? (legend.length > 1 ? true : false) : false,
        bottom: 15,
        right: 20,
        textStyle: {
          color: Color.echartItems.legend,
          fontSize: 12,
        },
        itemWidth: 14,
        itemHeight: 14,
        borderRadius: [0, 0, 0, 0],
      },
      // 直角坐标系内绘图网格
      grid: {
        left: gridLeft,
        right: gridRight,
        top: showBorder ? (title ? (yAxisUnit.length > 0 ? 100 : 80) : yAxisUnit.length > 0 ? 76 : 56) : title ? (yAxisUnit.length > 0 ? 90 : 70) : yAxisUnit.length > 0 ? 50 : 30, // 根据是否有边框、title、坐标轴显示名称动态调整
        bottom: showLegend ? (legend.length > 1 ? 60 : 40) : 40,
        containLabel: containLabel,
      },
      // 横轴
      xAxis: {
        nameTextStyle: {
          // Y轴名称文本样式
          color: Color.echartItems.title,
          fontSize: 12,
        },
        type: 'value',
        axisLine: {
          lineStyle: {
            color: Color.echartItems.xAxisLine,
          },
        },
        axisTick: {
          show: false,
        },
        axisLabel: {
          color: Color.echartItems.xAxisLabel,
          margin: 6, // 与横轴的距离
          fontSize: 12,
          formatter: (value, index) => {
            if (separator) {
              return this.handleNumberToString(value);
            }
            return percentStyle ? parseInt(value * 10000) / 100 + '%' : value;
          },
        },
      },
      // 纵轴
      yAxis: {
        name: yAxisUnit[0] ? yAxisUnit[0] : '',
        nameLocation: 'center',
        nameRotate: 0,
        nameTextStyle: {
          // Y轴名称文本样式
          color: Color.echartItems.title,
          fontSize: 12,
          padding: [0, -50, paddingHeight, 0],
        },
        type: 'category',
        data: yAxis,
        position: yAxisPosition,
        boundaryGap: true,
        axisLine: {
          show: false,
        },
        axisTick: {
          show: false,
        },
        axisLabel: {
          color: Color.echartItems.yAxisLabel,
          margin: 4, //与纵轴的距离
          fontSize: 12,
          interval: 0, // 设置成 0 强制显示所有标签。
          formatter: (value, index) => {
            if (value.includes('*')) {
              let arr = value.split('*');
              let res = `{red|*} ${arr[1]}`;
              return res;
            }
            return value;
            // if(value.length > 8){
            //     return value.substring(0 ,8)+'...';
            //   }else{
            //     return value;
            //   }
          },
          rich: {
            red: {
              color: Color.debtAndProfit.text[0],
            },
          },
        },
        splitLine: {
          lineStyle: {
            color: Color.echartItems.splitLine,
            width: 1,
          },
        },
      },
      series: series,
    };
  };

  handleNumberToString = (item) => {
    if (item || item === 0) {
      item = Number(item).toFixed(0);
      let number_arr = (item + '').split('.');
      if (Number(number_arr[1])) {
        return Number(number_arr[0]).toLocaleString() + '.' + number_arr[1];
      } else {
        return Number(number_arr[0]).toLocaleString();
      }
    } else {
      return '-';
    }
  };

  // 初始化图形
  initEchartsEvent = (e) => {
    if (!e) return;

    this.setState({
      instance: e.getEchartsInstance(), // echarts实例
    });
  };

  // （供外部调用）设置图例的选中与取消选中
  // type：select  unselect
  // name: 图例的名称
  setLegend = (type, name) => {
    let operaType = 'legendSelect';
    if (type == 'unselect') {
      operaType = 'legendUnSelect';
    }
    this.state.instance.dispatchAction({
      type: operaType,
      name: name,
    });
  };

  render() {
    const { series, yAxis, type, height, width, showBorder, percentStyle, isShowSeriesLabel, yAxisUnit, title, seriesLabelDataFormat, showLegend } = this.props;
    let legend = []; // 图例
    let seriesVals = []; // series
    let initStatus = series && yAxis; // 标记是否达到初始化状态(true:可以初始化图表，false：还未获取到数据)
    let chartHeight = height === 'auto' ? 200 : height; // 根据当前数据量的多少自动设置图形高度

    if (initStatus) {
      seriesVals = series.map((item, index) => {
        const yAxisIndex = item.yAxisIndex !== undefined ? item.yAxisIndex : 0; // 默认数据Y轴序号为0
        legend.push(item.name);
        let data = [];
        if (type === 'normal' || type === 'stack') {
          data = item.data;
        }
        if (type === 'debtAndProfit') {
          for (let i = 0; i < item.data.length; i++) {
            let element = item.data[i];
            data.push({
              value: element,
              itemStyle: {
                color: element != undefined && element > 0 ? this.debtAndProfitColor[0] : this.debtAndProfitColor[1],
              },
            });
          }
        }

        return {
          name: item.name,
          type: 'bar',
          barMaxWidth: 20,
          yAxisIndex,
          label: {
            show: type === 'stack' ? false : isShowSeriesLabel,
            position: 'right',
            color: Color.echartItems.yAxisLabel,
            fontSize: 12,
            formatter:
              seriesLabelDataFormat[index] == undefined
                ? (params) => {
                    if (percentStyle) {
                      let value = params.value;
                      // parseInt(value*10000)/100 解决js中浮点数的精度问题
                      return typeof value === 'number' && !isNaN(value) ? parseInt(value * 10000) / 100 + '%' : '--';
                    }
                  }
                : seriesLabelDataFormat[index],
          },
          data: data,
          stack: type === 'stack' ? '总量' : undefined,
        };
      });

      // 根据当前数据量的多少自动设置图形高度
      if (height === 'auto') {
        const top = showBorder
          ? title
            ? yAxisUnit.length > 0
              ? 80
              : 60
            : yAxisUnit.length > 0
            ? 56
            : 36
          : title
          ? yAxisUnit.length > 0
            ? 70
            : 50
          : yAxisUnit.length > 0
          ? 30
          : 10;
        const bottom = showLegend ? (legend.length > 1 ? 60 : 40) : 40;
        chartHeight = yAxis.length > 0 ? (top + bottom + yAxis.length * 25 + 30 > 1200 ? 1200 : top + bottom + yAxis.length * 25 + 30) : 200;
      }
    }
    let paddingHeight;
    if (yAxis && yAxis.length > 0) {
      if (yAxis.length % 2 === 0) {
        paddingHeight = Math.ceil(yAxis.length / 2) * 50 + 30;
      } else {
        paddingHeight = Math.ceil(yAxis.length / 2) * 50;
      }
    }
    return (
      <div style={{ border: showBorder && '1px solid #DDDDDD' }}>
        <Spin spinning={!initStatus} tip='加载中...'>
          {initStatus ? (
            series.length > 0 && yAxis.length > 0 ? (
              <ReactEcharts
                option={this.getOption(legend, seriesVals, paddingHeight)}
                style={{ height: chartHeight, width: width }}
                // 是否不跟之前设置的 option 进行合并，默认为 false，即合并。
                notMerge={true}
                onEvents={{
                  click: this.click,
                }}
                ref={this.initEchartsEvent}
              />
            ) : (
              <NoDataC />
            )
          ) : (
            // <Empty description='暂无数据' style={{height:chartHeight,display:'flex',justifyContent:'center',alignItems:'center',flexDirection:'column'}}></Empty>
            <div style={{ height: chartHeight, width: width }}></div>
          )}
        </Spin>
      </div>
    );
  }
}

/* 
 备注：
   当yAxis和series值为null或undefined时，显示loading状态
   当yAxis和series值为空数组[]时，显示“暂无数据”
   当yAxis和series值为有值的数组时，正常实现图形
 */
XYHorizontalChartsC.propTypes = {
  yAxis: PropTypes.array, // 纵轴数据（字符串数组）
  series: PropTypes.array, // 横向数据（[{name:'',data:[]},...]）
  type: PropTypes.oneOf([
    // 图表类型
    'normal', // 普通的横向柱状图
    'debtAndProfit', // 收益&负债类型的样式（红绿）
    'stack', // 堆叠图
  ]),
  height: PropTypes.oneOfType([
    // 图表高度（百分比、数值、auto（设置auto，则会根据当前数据量的多少自动设置图形高度））
    PropTypes.string,
    PropTypes.number,
  ]),
  width: PropTypes.oneOfType([
    // 图表宽度（百分比或数值）
    PropTypes.string,
    PropTypes.number,
  ]),
  colors: PropTypes.array, // 图表颜色
  title: PropTypes.string, // 标题
  toolTipFormat: PropTypes.func, // 提示框内容显示格式处理
  toolTipDataFormat: PropTypes.array, // 数据在提示框中显示的格式（与所在纵轴位置一致，从左向右，每一项用func表示，如[value=>parseInt(value)}, value=>value+'%',...]，，没有的项用空位表示）
  seriesLabelDataFormat: PropTypes.array, // 图形上的文本标签格式，若设置则展示标签，若不设置，则不显示标签([params=>params.data,,params=>params.data+'%',...])，默认数据量超过15条不展示
  yAxisUnit: PropTypes.array, // 纵轴上的单位（从左向右，每一项用字符串数据表示，没有的项用空位表示）
  percentStyle: PropTypes.bool, // 数据是否按百分比展示
  separator: PropTypes.bool, // 分隔符
  showBorder: PropTypes.bool, // 是否显示图形外层边框
  gridLeft: PropTypes.number, // 左轴距离左侧距离
  gridRight: PropTypes.number, // 右轴距离右侧距离
  isShowSeriesLabel: PropTypes.bool, // 是否显示图形上的文本
  showLegend: PropTypes.bool, // 是否展示图例
  yAxisPosition: PropTypes.string, // 设置纵轴位置（left  right）
  onRef: PropTypes.func, // 本组件的引用（可用来父组件调用内部方法）
  showTooltipLabel: PropTypes.bool, // 是否展示提示信息的label
  containLabel: PropTypes.bool, // grid区域是否包含坐标轴的刻度标签
  click: PropTypes.func, // 点击事件
};

export default XYHorizontalChartsC;
